package com.frost500.integrationdemo.controller;

import com.frost500.integrationdemo.model.Storage;
import com.frost500.integrationdemo.service.StorageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@RestController
@RequestMapping("/storage")
public class StorageController {

    @Autowired
    private StorageService storageService;

    @Autowired
    private RedisLockRegistry redisLockRegistry;

    private static Lock lock = new ReentrantLock();

    /**
     * 无锁扣减库存
     *
     * @param id
     * @return
     */
    @PutMapping("/{id}/deductUnlock")
    public ResponseEntity<Void> deductUnlock(@PathVariable("id") Long id) {
        storageService.deductUnlock(id);
        return ResponseEntity.noContent().build();
    }

    /**
     * 加锁扣减库存
     *
     * @param id
     * @return
     */
    @PutMapping("/{id}/deductLocked")
    public ResponseEntity<Void> deductLocked(@PathVariable("id") Long id) {
        try {
            lock.lock();
            storageService.deductLocked(id);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return ResponseEntity.noContent().build();
    }

    /**
     * 加锁扣减库存
     *
     * @param id
     * @return
     */
    @PutMapping("/{id}/deductDistributeLocked")
    public ResponseEntity<Void> deductDistributeLocked(@PathVariable("id") Long id) {
        Lock distributeLock = redisLockRegistry.obtain("lock");
        try {
            distributeLock.lock();
            storageService.deductDistributeLocked(id);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            distributeLock.unlock();
        }
        return ResponseEntity.noContent().build();
    }

    @PutMapping("/insertStorage")
    public ResponseEntity<Void> insertStorage() {
        storageService.insertStorage();
        return ResponseEntity.noContent().build();
    }

    @PutMapping("/insertStorageLocked")
    public ResponseEntity<Void> insertStorageLocked() {
        lock.lock();
        try {
            storageService.insertStorageLocked();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.lock();
        }
        return ResponseEntity.noContent().build();
    }

    @PutMapping("/insertStorageDistributeLocked")
    public ResponseEntity<Void> insertStorageDistributeLocked() {
        Lock distributeLock = redisLockRegistry.obtain("lock");
        try {
            distributeLock.lock();
            storageService.insertStorageDistributeLocked();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            distributeLock.unlock();
        }
        return ResponseEntity.noContent().build();
    }

    @GetMapping("/getAll")
    public ResponseEntity<List<Storage>> getAll(){
        return ResponseEntity.ok(storageService.getAll());
    }
}
